﻿using System;
using System.Collections.Generic;
using System.Text;
using URSA.Tools;

namespace URSA.Tools
{
    /// <summary>
    /// Contains some useful functions
    /// </summary>
    public class Utilities
    {
		/// <summary>
		/// Exception handler
		/// </summary>
		/// <param name="error"></param>
		public delegate void ExceptionHandler(Exception error);
		
		/// <summary>
		/// Fires when an exception is raised.
		/// </summary>
		public static event ExceptionHandler OnError;

		private static void HandleException(Exception error)
		{
			if (OnError != null)
			{
				OnError(error);
			}
		}

		private static string ScanForFTDISerial(string serialOverride)
		{
			string selectedNodeSerial = string.Empty;

			FTDIDeviceInfoNode[] nodes = URSAPort.ListDevices();

			// Check for an FTDI device
			if (nodes.Length == 0)
			{
				throw new Exception("No FTDI nodes found, could not detect pc dongle");
			}

			//We can assume that only one device is connected unless serial is provided
			if (serialOverride != null)
			{
				foreach (FTDIDeviceInfoNode node in nodes)
				{
					if (node.SerialNumber == serialOverride)
					{
						selectedNodeSerial = node.SerialNumber;
					}
				}
				if (selectedNodeSerial == string.Empty)
				{
					throw new Exception("Could not find serial override specified");
				}
			}
			else
			{
				//Look for first FTDI node connected to the system
				selectedNodeSerial = ((FTDIDeviceInfoNode)nodes.GetValue(nodes.GetLowerBound(0))).SerialNumber;
			}

			if (selectedNodeSerial == string.Empty)
			{
				throw new Exception("Could not retrieve serial for FTDI node.");
			}

			return selectedNodeSerial;
		}

		/// <summary>
		/// Scan for, connect and return a URSA USB port instance.
		/// </summary>
		/// <param name="serialOverride">In the case of multiple dongles connected to the pc, 
		/// the method will return the first it find, use the dongle's serial to override this.
		/// Most of the time there will only by a single dongle connected so this can be ignored.
		/// </param>
		/// <returns>The port connected to the usb dongle</returns>
		public static URSAPort CreatePort(string serialOverride = null)
		{
			try
			{
				string selectedNodeSerial = ScanForFTDISerial(serialOverride);

				URSAPort newPort = new URSAPort();

				newPort.showDebugInformationOnConsole = true;

				newPort.OpenBySerialNumber(selectedNodeSerial);

				return newPort;

			}
			catch (Exception error)
			{
				HandleException(error);
			}

			return null;
		}

		/// <summary>
		/// Returns the string representation of the bytes in hex form
		/// </summary>
		/// <param name="data">A number of bytes</param>
		/// <returns>A formatted string containing the bytes in hex representation</returns>
		public static string ConvertByteArrayToString(byte[] data)
		{
			string results = "";

			foreach (byte aByte in data)
			{
				results += string.Format("{0:x2} ", aByte);
			}

			return results;
		}
    }
}